/*****************************************************************************
 * Copyright (c) 2013, 2017, 2021 Borland Software Corporation, CEA LIST, ALL4TEC, Artal and others.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * Michael Golubev (Montages) - initial API and implementation
 * CEA LIST - initial API and implementation
 * Mickael ADAM (ALL4TEC) mickael.adam@all4tec.net - Bug 510587: the palette must not be generated by using GMF gen
 * Etienne Allogo (ARTAL) - etienne.allogo@artal.fr - Bug 569174 : 1.4 Merge papyrus extension templates into codegen.xtend
 * Etienne Allogo (ARTAL) - etienne.allogo@artal.fr - Bug 569174 : L1.2 clean up
 *****************************************************************************/
package xpt.plugin

import com.google.inject.Inject
import com.google.inject.Singleton
import org.eclipse.emf.ecore.EObject
import org.eclipse.papyrus.gmf.codegen.gmfgen.AbstractToolEntry
import org.eclipse.papyrus.gmf.codegen.gmfgen.GenCompartment
import org.eclipse.papyrus.gmf.codegen.gmfgen.GenDiagram
import org.eclipse.papyrus.gmf.codegen.gmfgen.GenEditorGenerator
import org.eclipse.papyrus.gmf.codegen.gmfgen.GenExternalNodeLabel
import org.eclipse.papyrus.gmf.codegen.gmfgen.GenLink
import org.eclipse.papyrus.gmf.codegen.gmfgen.GenLinkLabel
import org.eclipse.papyrus.gmf.codegen.gmfgen.GenMetricContainer
import org.eclipse.papyrus.gmf.codegen.gmfgen.GenPlugin
import org.eclipse.papyrus.gmf.codegen.gmfgen.ToolEntry
import org.eclipse.papyrus.gmf.codegen.gmfgen.ToolGroup
import xpt.Common
import xpt.GenEditorGenerator_qvto
import xpt.editor.extensions
import xpt.editor.palette.Utils_qvto

@Singleton class plugin {

	@Inject extension GenEditorGenerator_qvto
	@Inject extension Common
	@Inject extension pluginUtils
	@Inject extension Utils_qvto

	@Inject extensions xptEditorExtension
	@Inject xpt.diagram.preferences.extensions xptPreferencesExtension
	@Inject xpt.propsheet.extensions xptPropsheetExtension
	@Inject xpt.navigator.extensions xptNavigatorExtension
	@Inject xpt.application.extensions xptApplicationExtension
	@Inject xpt.diagram.updater.extensions xptUpdaterExtension
	@Inject impl.actions.extensions xptActionExtension
	@Inject xpt.providers.extensions xptProvidersExtension

	def qualifiedClassName(GenPlugin it) '''plugin.xml'''

	def fullPath(GenPlugin it) '''«qualifiedClassName(it)»'''

	def plugin(GenPlugin it) '''
		<?xml version="1.0" encoding="UTF-8"?>
		<?eclipse version="3.0"?>
		«xcopyright(it.editorGen)»
		<plugin>
		««««fileTypes()»
		««««extension_parser()»
		«xptEditorExtension.extensions(it.editorGen)»
		«««global actions handled in the diagram.common plugin
		««««pluginMenu()»
		«validation(it.editorGen.diagram)»
		«IF it.editorGen.metrics !== null »«metrics(it.editorGen.metrics)»«ENDIF»
		«««RS: redefine palette generation
		«««		«palettePredefinedEntries(editorGen)»
		«««		«paletteEntries(editorGen)»
		«xptPreferencesExtension.extensions(it.editorGen.diagram)»
		«IF it.editorGen.propertySheet !== null »«xptPropsheetExtension.extensions(it.editorGen.propertySheet)»«ENDIF»
		«xptProvidersExtension.extensions(it.editorGen.diagram)»
		«IF it.editorGen.navigator !== null »«xptNavigatorExtension.extensions(it.editorGen.navigator)»«ENDIF»
		«IF it.editorGen.application !== null »«xptApplicationExtension.extensions(it.editorGen.application)»«ENDIF»
		«extensionsConstraintProviders(it.editorGen)»
		«xptUpdaterExtension.extensions(it.editorGen.diagramUpdater)»
		«xptActionExtension.Main(it.editorGen)»
		«additions(it)»
		«notationTypesMap(editorGen)»
		«««		«paletteConfiguration(editorGen)»
		</plugin>
	'''

	def fileTypes(GenPlugin it) '''
		«tripleSpace(1)»<extension point="org.eclipse.team.core.fileTypes" id="repo-ftype">
		«tripleSpace(2)»«xmlGeneratedTag»
		«tripleSpace(2)»<fileTypes type="text" extension="«editorGen.diagramFileExtension»"/>
		«tripleSpace(1)»</extension>
	'''

	def extension_parser(GenPlugin it) '''
		«tripleSpace(1)»<extension point="org.eclipse.emf.ecore.extension_parser" id="resource-factory">
		«tripleSpace(2)»«xmlGeneratedTag»
		«tripleSpace(2)»<parser
		«tripleSpace(3)»type="«editorGen.diagramFileExtension»"
		«tripleSpace(3)»class="org.eclipse.gmf.runtime.emf.core.resources.GMFResourceFactory">
		«tripleSpace(2)»</parser>
		«tripleSpace(1)»</extension>
	'''

	def pluginMenu(GenPlugin it) '''
		«outTab»
		«tripleSpace(1)»<extension point="org.eclipse.gmf.runtime.common.ui.services.action.globalActionHandlerProviders" id="global-actions">
		«tripleSpace(2)»«xmlGeneratedTag»
		«tripleSpace(2)»<GlobalActionHandlerProvider
		«tripleSpace(3)»class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramGlobalActionHandlerProvider"
		«tripleSpace(3)»id="«editorGen.modelID»Presentation">
		«tripleSpace(3)»<Priority name="Lowest"/>
		«tripleSpace(3)»<ViewId id="«editorGen.editor.ID»">
		«tripleSpace(4)»<ElementType class="org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart">
		«tripleSpace(5)»<GlobalActionId actionId="delete"/>
		«tripleSpace(4)»</ElementType>
		«tripleSpace(4)»<ElementType class="org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart">
		«tripleSpace(5)»<GlobalActionId actionId="save"/>
		«tripleSpace(4)»</ElementType>
		«tripleSpace(4)»<ElementType class="org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart">
		«tripleSpace(5)»<GlobalActionId actionId="save">
		«tripleSpace(5)»</GlobalActionId>
		«tripleSpace(4)»</ElementType>        
		«tripleSpace(3)»</ViewId>
		«tripleSpace(2)»</GlobalActionHandlerProvider>
		«IF printingEnabled»
			«tripleSpace(2)»<GlobalActionHandlerProvider
			«tripleSpace(3)»class="org.eclipse.gmf.runtime.diagram.ui.printing.render.providers.DiagramWithPrintGlobalActionHandlerProvider"
			«tripleSpace(3)»id="«editorGen.modelID»PresentationPrint">
			«tripleSpace(3)»<Priority name="Lowest"/>
			«tripleSpace(3)»<ViewId id="«editorGen.editor.ID»">
			«tripleSpace(4)»<ElementType class="org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart">
			«tripleSpace(5)»<GlobalActionId actionId="print"/>
			«tripleSpace(4)»</ElementType>
			«tripleSpace(3)»</ViewId>
			«tripleSpace(2)»</GlobalActionHandlerProvider>
		«ENDIF»
		«IF null === editorGen.application »
			«tripleSpace(2)»<GlobalActionHandlerProvider
			«tripleSpace(3)»class="org.eclipse.gmf.runtime.diagram.ui.providers.ide.providers.DiagramIDEGlobalActionHandlerProvider"
			«tripleSpace(3)»id="«editorGen.modelID»PresentationIDE">
			«tripleSpace(3)»<Priority name="Lowest"/>
			«tripleSpace(3)»<ViewId id="«editorGen.editor.ID»">
			«tripleSpace(4)»<ElementType class="org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart">
			«tripleSpace(5)»<GlobalActionId actionId="bookmark"/>
			«tripleSpace(4)»</ElementType>
			«tripleSpace(3)»</ViewId>
			«tripleSpace(2)»</GlobalActionHandlerProvider>
		«ENDIF»
		«tripleSpace(2)»<GlobalActionHandlerProvider
		«tripleSpace(4)»class="org.eclipse.gmf.runtime.diagram.ui.render.providers.DiagramUIRenderGlobalActionHandlerProvider"
		«tripleSpace(4)»id="«editorGen.modelID»Render">
		«tripleSpace(3)»<Priority name="Lowest"/>
		«tripleSpace(3)»<ViewId id="«editorGen.editor.ID»">
		«tripleSpace(4)»<ElementType class="org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart">
		«tripleSpace(5)»<GlobalActionId actionId="cut"/>
		«tripleSpace(5)»<GlobalActionId actionId="copy"/>
		«tripleSpace(5)»<GlobalActionId actionId="paste"/>
		«tripleSpace(4)»</ElementType>
		«tripleSpace(3)»</ViewId>
		«tripleSpace(2)»</GlobalActionHandlerProvider>
		«tripleSpace(1)»</extension>

	'''

	def metrics(GenMetricContainer it) '''
		«IF metrics.size() > 0»

		«tripleSpace(1)»<extension id="metrics-view" point="org.eclipse.ui.views">
		«tripleSpace(2)»«xmlGeneratedTag»
		«tripleSpace(2)»<view class="«editorGen.diagram.getMetricProviderQualifiedClassName()»$ResultView"
		«tripleSpace(4)»id="«editorGen.diagram.getMetricViewID()»"
		«tripleSpace(4)»name="«editorGen.modelID» Diagram Metrics"/>
		«tripleSpace(1)»</extension>
		«ENDIF»
	'''

	def validation(GenDiagram it) '''
		«IF validationEnabled || hasAudits(editorGen)»
			«IF null === editorGen.application »
				«tripleSpace(1)»<extension point="org.eclipse.gmf.runtime.common.ui.services.markerNavigationProviders" id="markers-navigation">
				«tripleSpace(2)»«xmlGeneratedTag»
				«tripleSpace(2)»<MarkerNavigationProvider class="«getMarkerNavigationProviderQualifiedClassName()»">
				«tripleSpace(3)»<MarkerType name="«editorGen.plugin.ID + '.' + getValidationDiagnosticMarkerType()»"/>
				«tripleSpace(3)»<Priority name="«markerNavigationProviderPriority»"/>
				«tripleSpace(2)»</MarkerNavigationProvider>
				«tripleSpace(1)»</extension>

				«tripleSpace(1)»<extension id="«getValidationDiagnosticMarkerType()»" name="«editorGen.plugin.name» problems" point="org.eclipse.core.resources.markers">
				«tripleSpace(2)»«xmlGeneratedTag»
				«tripleSpace(2)»<super type="org.eclipse.core.resources.problemmarker"/>
				«tripleSpace(2)»<super type="org.eclipse.gmf.runtime.common.ui.services.marker"/>
				«tripleSpace(2)»<persistent value="true"/>
				«tripleSpace(1)»</extension>   
			«ENDIF»
			«IF validationDecorators»

				«tripleSpace(1)»<extension id="validationDecoratorProvider" name="ValidationDecorations" point="org.eclipse.gmf.runtime.diagram.ui.decoratorProviders">
				«tripleSpace(2)»«xmlGeneratedTag»
				«tripleSpace(2)»<decoratorProvider class="«getValidationDecoratorProviderQualifiedClassName()»">
				«tripleSpace(3)»<Priority name="«validationDecoratorProviderPriority»"/>
				«tripleSpace(3)»<object class="org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart(org.eclipse.gmf.runtime.diagram.ui)" id="PRIMARY_VIEW"/>
				«tripleSpace(3)»<context decoratorTargets="PRIMARY_VIEW"/>
				«tripleSpace(2)»</decoratorProvider>
				«tripleSpace(1)»</extension>
			«ENDIF»
		«ENDIF»
	'''

	def additions(GenPlugin it) ''''''

	//	def category(GenDiagram it) '''«getDiagramPreferencePageCategory()».«editorGen.modelID»'''

	//RS: redefine palette generation, using predefined entries
	def palettePredefinedEntries(GenEditorGenerator it) '''
		«xmlGeneratedTag»
		<extension
			id="«plugin.name».palettedefinition"
			name="«plugin.name» Predefined Entries"
			point="org.eclipse.gmf.runtime.diagram.ui.paletteProviders"> 

			«xmlGeneratedTag»	
			<paletteProvider class="org.eclipse.gmf.runtime.diagram.ui.providers.DefaultPaletteProvider">
				<Priority name="Lowest"/>
				   		<contribution
				   		    	factoryClass="«it.diagram.palette.packageName».«it.diagram.palette.factoryClassName»">
				   		<predefinedEntry id="standardGroup/noteStack/noteTool" remove="true"/> 
				<predefinedEntry id="standardGroup/noteStack/textTool" remove="true"/> 
				<predefinedEntry id="standardGroup/noteStack/noteattachmentTool" remove="true"/>

				«FOR tool : collectTools(diagram.palette)»
					«predefinedEntryDefinition(tool)»
				«ENDFOR»

				</contribution>
			</paletteProvider>	

		</extension>
	'''

	def outTab() {
		return '	';
	}

	/**
	 * deprecated: palette configuration are now declared through architecture model.
	 */
	def paletteConfiguration(GenEditorGenerator it) '''
		<extension point="org.eclipse.papyrus.infra.gmfdiag.common.paletteDefinition">
			«xmlGeneratedTag»
			<paletteDefinition
				ID="«plugin.ID».paletteconfiguration"
				class="org.eclipse.papyrus.infra.gmfdiag.common.service.palette.ExtendedPluginPaletteProvider"
				name="«plugin.name» Palette"
				path="«relativePath»/«modelID».paletteconfiguration"
				provider="Eclipse Modeling Project">
				<Priority
					name="Lowest">
				</Priority>
				<!-- Specify diagram to which this palette tool relates -->
				<editor
					id="«plugin.ID»">
				</editor>
			</paletteDefinition>
		</extension>
	'''

	//RS: redefine palette generation, using predefined entries
	def paletteEntries(GenEditorGenerator it) '''
		«xmlGeneratedTag»
		<extension
			id="«plugin.name».standard"
			name="«plugin.name» Standard Palette"
			point="org.eclipse.gmf.runtime.diagram.ui.paletteProviders"> 

			«xmlGeneratedTag»	
			<paletteProvider class="org.eclipse.gmf.runtime.diagram.ui.providers.DefaultPaletteProvider">
				<Priority name="Low"/>
				   		<contribution
				   		    	factoryClass="«it.diagram.palette.packageName».«it.diagram.palette.factoryClassName»">
				   		<predefinedEntry id="standardGroup/noteStack/noteTool" remove="true"/> 
				<predefinedEntry id="standardGroup/noteStack/textTool" remove="true"/> 
				<predefinedEntry id="standardGroup/noteStack/noteattachmentTool" remove="true"/>

				«FOR tool : diagram.palette.groups»
					«groupUsage(tool)»
					««« TODO: call sub entries... 
					«FOR entry : tool.entries.filter[e| e instanceof ToolEntry]»
						«toolUsage(entry, tool)»
					«ENDFOR»
					«FOR entry : tool.entries.filter[e| e instanceof ToolGroup]»
						«toolUsage(entry, tool)»
					«ENDFOR»
				«ENDFOR»
				</contribution>
				<editor id="«plugin.ID»"/>
			</paletteProvider>	

		</extension>
	'''

	def groupUsage(ToolGroup it) '''
		<entry
		      description="«it.description»"
		      id=«IF isQuoted(id,'"')»«id»«ELSE»"«id»"«ENDIF»
		      kind="«IF it.stack && it.toolsOnly»stack«ELSE»drawer«ENDIF»"
		      label="«it.title»"
		      large_icon="«largeIconPath»"
		      path="«getPath(it)»"
		      small_icon="«smallIconPath»">
		   <expand
		         force="true">
		   </expand>
		</entry>
	'''

	private def getPath(ToolEntry it) {
		return buildPath(it.eContainer);
	}

	private def getPath(ToolGroup it) {
		return buildPath(it.eContainer);
	}

	private def buildPath(EObject it) {
		var path = new StringBuilder();
		var container = it;
		while (container instanceof ToolGroup) {
			path.insert(0, getToolPath((container as ToolGroup).id));
			container = container.eContainer;
		}
		return if(path.length() != 0) path.toString else "/" ;
	}

	def dispatch toolUsage(ToolEntry it, ToolGroup group) '''
 		<predefinedEntry
 		        id=«IF isQuoted(id,'"')»«id»«ELSE»"«id»"«ENDIF»
 				path="«getPath(it)»">
 		  </predefinedEntry>
 	'''

	def dispatch toolUsage(ToolGroup it, ToolGroup group) '''
		«groupUsage(it)»
	'''

	def predefinedEntryDefinition(AbstractToolEntry it) '''
		<entry
		      defineOnly="true"
		      description="«it.description»"
		      id=«IF isQuoted(id,'"')»«id»«ELSE»"«id»"«ENDIF»
		      kind="tool"
		      label="«it.title»"
		      large_icon="«largeIconPath»"
		      path=""
		      small_icon="«smallIconPath»">
		</entry>
	'''

	//	set notation type mapping extension point
	def notationTypesMap(GenEditorGenerator it) '''	
		«tripleSpace(0)»<extension point="org.eclipse.papyrus.infra.gmfdiag.common.notationTypesMapping"> 
		«tripleSpace(1)»«xmlGeneratedTag»
		«tripleSpace(1)»<diagramMappings diagramID="«modelID»">
		«tripleSpace(1)»	<mapping type="«modelID»" humanReadableType="«modelID.replaceAll('Papyrus|UML|Diagram', '')»Diagram"/>
			«FOR compartment : diagram.compartments»
				«compartmentToTypeMap(compartment)»
			«ENDFOR»
			«FOR link : diagram.links»
				«linksToTypeMap(link)»
			«ENDFOR»
			«FOR externalLabel : diagram.eResource.allContents.filter(typeof (GenExternalNodeLabel)).toIterable»
				«floatingLabelToTypeMap(externalLabel)»
				«externalNodeLabelToTypeMap(externalLabel)»
			«ENDFOR»
		«tripleSpace(1)»</diagramMappings>
		«tripleSpace(0)»</extension>
	'''

	def compartmentToTypeMap(GenCompartment it) '''
		<mapping
			humanReadableType="«title.replaceAll('Compartment', '')»"
			type="«stringVisualID»">
		</mapping>
	'''

	def linksToTypeMap(GenLink it) '''
		«FOR label : labels»
			«linkLabelToTypeMap(label)»
		«ENDFOR»
	'''

	def linkLabelToTypeMap(GenLinkLabel it)'''
	«««	it is used on a LabelVisibilityPreference...
		«IF labelVisibilityPreference !== null »
			<mapping
				humanReadableType="«labelVisibilityPreference.role»"
				type="«stringVisualID»">
			</mapping>
		«ENDIF»
	'''

	def externalNodeLabelToTypeMap(GenExternalNodeLabel it)'''
		«IF labelVisibilityPreference !== null »
			<mapping
				humanReadableType="«labelVisibilityPreference.role»"
				type="«stringVisualID»">
			</mapping>
		«ENDIF»
	'''

	def floatingLabelToTypeMap(GenExternalNodeLabel it)'''
	«««	it is used on a ExtensionGenView...
	«IF superEditPart !== null»
		«
		//		«««...to be extended as floatingLabel
		IF "FloatingLabelEditPart".equals(name) »
			<mapping
				humanReadableType="Floating Label"
				type="«stringVisualID»">
			</mapping>
		«ENDIF»
	«ENDIF»	
	'''
}
